home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / fs / unassmbl.c < prev    next >
C/C++ Source or Header  |  1995-03-23  |  32KB  |  1,239 lines

  1. /* This is file UNASSMBL.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified by Morten Welinder, terra@diku.dk, for use with full screen
  16.    debugger.  These changes are copyright 1994 by Morten Welinder.
  17.  
  18.    Known bugs (fixed = +, not fixed = -):
  19.    - string instructions don't display overriden segment.
  20.    + "aad"/"aam" did't display immediate byte (and therefore got the length
  21.      of the instruction wrong).
  22.    + the tables had an entry at 0x82; that's a bug from Intel's manuals.
  23.    - there are no entries for 486 instructions ("invd", "wbinvd", "xadd",
  24.      "xcmpxchg", "bswap", and "invlpg")
  25.    + "jnc" and "jc" were swapped.  Twice.
  26.    + "setnc" and "setc" were swapped.
  27.    + "setp"/"setnp" should have been "setpe"/"setpo" for consistency.
  28.    */
  29. /* Modified by Long Doan, ld@netrix.com. These changes are copyrighted
  30.    1994-1995 by Long Doan                                          */
  31.  
  32. #include <stdio.h>
  33. #include <string.h>
  34.  
  35. #include "ed.h"
  36. #include "unassmbl.h"
  37. #include "syms.h"
  38.  
  39. #define SOURCE_LIST
  40. #ifndef FULLSCR
  41. #define FULLSCR
  42. #endif
  43.  
  44. int seg_size=32;
  45.  
  46. static word8 buf[20];
  47. static word32 vaddr;
  48. static int bufp, bufe;
  49. static char ubuf[100], *ubufp;
  50. static col;
  51.  
  52. static void ua_str(char *s);
  53.  
  54. /* Percent tokens in strings:
  55.    First char after '%':
  56.         A - direct address
  57.         C - reg of r/m picks control register
  58.         D - reg of r/m picks debug register
  59.         E - r/m picks operand
  60.         F - flags register
  61.         G - reg of r/m picks general register
  62.         I - immediate data (takes extended size, data size)
  63.         J - relative IP offset
  64.         M - r/m picks memory
  65.         O - no r/m, offset only
  66.         R - mod of r/m picks register only
  67.         S - reg of r/m picks segment register
  68.         T - reg of r/m picks test register
  69.         X - DS:ESI
  70.         Y - ES:EDI
  71.         2 - prefix of two-byte opcode
  72.         e - put in 'e' if use32 (second char is part of reg name)
  73.             put in 'w' for use16 or 'd' for use32 (second char is 'w')
  74.     f - floating point (second char is esc value)
  75.         g - do r/m group 'n'
  76.         p - prefix
  77.         s - size override (second char is a,o)
  78.         + - make default signed
  79.    Second char after '%':
  80.         a - two words in memory (BOUND)
  81.         b - byte
  82.         c - byte or word
  83.     d - dword
  84.         p - 32 or 48 bit pointer
  85.         s - six byte pseudo-descriptor
  86.         v - word or dword
  87.         w - word
  88.         F - use floating regs in mod/rm
  89.         + - always sign
  90.         - - sign if negative
  91.         1-8 - group number, esc value, etc
  92. */
  93.  
  94. char *opmap1[] = {
  95. /* 0 */
  96.   "add %Eb,%Gb", "add %Ev,%Gv", "add %Gb,%Eb", "add %Gv,%Ev",
  97.   "add al,%I-bb", "add %eax,%I-vv", "push es", "pop es",
  98.   "or %Eb,%Gb", "or %Ev,%Gv", "or %Gb,%Eb", "or %Gv,%Ev",
  99.   "or al,%Ibb", "or %eax,%Ivv", "push cs", "%2 ",
  100. /* 1 */
  101.   "adc %Eb,%Gb", "adc %Ev,%Gv", "adc %Gb,%Eb", "adc %Gv,%Ev",
  102.   "adc al,%I-bb", "adc %eax,%I-vv", "push ss", "pop ss",
  103.   "sbb %Eb,%Gb", "sbb %Ev,%Gv", "sbb %Gb,%Eb", "sbb %Gv,%Ev",
  104.   "sbb al,%I-bb", "sbb %eax,%I-vv", "push ds", "pop ds",
  105. /* 2 */
  106.   "and %Eb,%Gb", "and %Ev,%Gv", "and %Gb,%Eb", "and %Gv,%Ev",
  107.   "and al,%Ibb", "and %eax,%Ivv", "%pe", "daa",
  108.   "sub %Eb,%Gb", "sub %Ev,%Gv", "sub %Gb,%Eb", "sub %Gv,%Ev",
  109.   "sub al,%I-bb", "sub %eax,%I-vv", "%pc", "das",
  110. /* 3 */
  111.   "xor %Eb,%Gb", "xor %Ev,%Gv", "xor %Gb,%Eb", "xor %Gv,%Ev",
  112.   "xor al,%Ibb", "xor %eax,%Ivv", "%ps", "aaa",
  113.   "cmp %Eb,%Gb", "cmp %Ev,%Gv", "cmp %Gb,%Eb", "cmp %Gv,%Ev",
  114.   "cmp al,%I-bb", "cmp %eax,%I-vv", "%pd", "aas",
  115. /* 4 */
  116.   "inc %eax", "inc %ecx", "inc %edx", "inc %ebx",
  117.   "inc %esp", "inc %ebp", "inc %esi", "inc %edi",
  118.   "dec %eax", "dec %ecx", "dec %edx", "dec %ebx",
  119.   "dec %esp", "dec %ebp", "dec %esi", "dec %edi",
  120. /* 5 */
  121.   "push %eax", "push %ecx", "push %edx", "push %ebx",
  122.   "push %esp", "push %ebp", "push %esi", "push %edi",
  123.   "pop %eax", "pop %ecx", "pop %edx", "pop %ebx",
  124.   "pop %esp", "pop %ebp", "pop %esi", "pop %edi",
  125. /* 6 */
  126.   "pusha", "popa", "bound %Gv,%Ma", "arpl %Ew,%Rw",
  127.   "%pf", "%pg", "%so", "%sa",
  128.   "push %I-vv", "imul %Gv=%Ev*%I-vv", "push %I-vb", "imul %Gv=%Ev*%I-vb",
  129.   "insb %Yb,dx", "ins%ew %Yv,dx", "outsb dx,%Xb", "outs%ew dx,%Xv",
  130. /* 7 */
  131.   "jo %Jb", "jno %Jb", "jc %Jb",  "jnc %Jb",
  132.   "jz %Jb", "jnz %Jb", "jbe %Jb", "jnbe %Jb",
  133.   "js %Jb", "jns %Jb", "jpe %Jb", "jpo %Jb",
  134.   "jl %Jb", "jge %Jb", "jle %Jb", "jg %Jb",
  135. /* 8 */
  136.   "%g1 %Eb,%Ibb", "%g1 %Ev,%Ivv", 0, "%g1 %Ev,%Ivb",
  137.   "test %Eb,%Gb", "test %Ev,%Gv", "xchg %Eb,%Gb", "xchg %Ev,%Gv",
  138.   "mov %Eb,%Gb", "mov %Ev,%Gv", "mov %Gb,%Eb", "mov %Gv,%Ev",
  139.   "mov %Ew,%Sw", "lea %Gv,%M ", "mov %Sw,%Ew", "pop %Ev",
  140. /* 9 */
  141.   "nop", "xchg %eax,%ecx", "xchg %eax,%edx", "xchg %eax,%ebx",
  142.   "xchg %eax,%esp", "xchg %eax,%ebp", "xchg %eax,%esi", "xchg %eax,%edi",
  143.   "cbw", "cwd", "call %Ap", "fwait",
  144.   "push %eflags", "pop %eflags", "sahf", "lahf",
  145. /* a */
  146.   "mov al,%Ob", "mov %eax,%Ov", "mov %Ob,al", "mov %Ov,%eax",
  147.   "movsb %Xb,%Yb", "movs%ew %Xv,%Yv", "cmpsb %Xb,%Yb", "cmps%ew %Xv,%Yv",
  148.   "test al,%Ibb", "test %eax,%Ivv", "stosb %Yb,al", "stos%ew %Yv,%eax",
  149.   "lodsb al,%Xb", "lods%ew %eax,%Xv", "scasb al,%Xb", "scas%ew %eax,%Xv",
  150. /* b */
  151.   "mov al,%Ibb", "mov cl,%Ibb", "mov dl,%Ibb", "mov bl,%Ibb",
  152.   "mov ah,%Ibb", "mov ch,%Ibb", "mov dh,%Ibb", "mov bh,%Ibb",
  153.   "mov %eax,%I-vv", "mov %ecx,%I-vv", "mov %edx,%I-vv", "mov %ebx,%I-vv",
  154.   "mov %esp,%Ivv", "mov %ebp,%Ivv", "mov %esi,%I-vv", "mov %edi,%I-vv",
  155. /* c */
  156.   "%g2 %Eb,%Ibb", "%g2 %Ev,%Ibb", "ret %Iw", "ret",
  157.   "les %Gv,%Mp", "lds %Gv,%Mp", "mov %Eb,%Ibb", "mov %Ev,%I-vv",
  158.   "enter %Iww,%Ibb", "leave", "retf %Iww", "retf",
  159.   "int 3", "int %Ibb", "into", "iret",
  160. /* d */
  161.   "%g2 %Eb,1", "%g2 %Ev,1", "%g2 %Eb,cl", "%g2 %Ev,cl",
  162.   "aam %Ibb", "aad %Ibb", 0, "xlat",
  163.   "%f0", "%f1", "%f2", "%f3",
  164.   "%f4", "%f5", "%f6", "%f7",
  165. /* e */
  166.   "loopne %Jb", "loope %Jb", "loop %Jb", "jcxz %Jb",
  167.   "in al,%Ibb", "in %eax,%Ibb", "out %Ibb,al", "out %Ibb,%eax",
  168.   "call %Jv", "jmp %Jv", "jmp %Ap", "jmp %Jb",
  169.   "in al,dx", "in %eax,dx", "out dx,al", "out dx,%eax",
  170. /* f */
  171.   "lock %p ", 0, "repne %p ", "rep(e) %p ",
  172.   "hlt", "cmc", "%g3", "%g0",
  173.   "clc", "stc", "cli", "sti",
  174.   "cld", "std", "%g4", "%g5"
  175.   };
  176.  
  177. char *second[] = {
  178. /* 0 */
  179.   "%g6", "%g7", "lar %Gv,%Ew", "lsl %Gv,%Ew", 0, 0, "clts", 0,
  180.   0, 0, 0, 0, 0, 0, 0, 0,
  181. /* 1 */
  182.   0, 0, 0, 0, 0, 0, 0, 0,
  183.   0, 0, 0, 0, 0, 0, 0, 0,
  184. /* 2 */
  185.   "mov %Rd,%Cd", "mov %Rd,%Dd", "mov %Cd,%Rd", "mov %Dd,%Rd",
  186.   "mov %Rd,%Td", 0, "mov %Td,%Rd", 0,
  187.   0, 0, 0, 0, 0, 0, 0, 0,
  188. /* 3 */
  189.   0, 0, 0, 0, 0, 0, 0, 0,
  190.   0, 0, 0, 0, 0, 0, 0, 0,
  191.   0, 0, 0, 0, 0, 0, 0, 0,
  192.   0, 0, 0, 0, 0, 0, 0, 0,
  193.   0, 0, 0, 0, 0, 0, 0, 0,
  194.   0, 0, 0, 0, 0, 0, 0, 0,
  195.   0, 0, 0, 0, 0, 0, 0, 0,
  196.   0, 0, 0, 0, 0, 0, 0, 0,
  197.   0, 0, 0, 0, 0, 0, 0, 0,
  198.   0, 0, 0, 0, 0, 0, 0, 0,
  199. /* 8 */
  200.   "jo %Jv", "jno %Jv", "jc %Jv",  "jnc %Jv",
  201.   "jz %Jv", "jnz %Jv", "jbe %Jv", "jnbe %Jv",
  202.   "js %Jv", "jns %Jv", "jpe %Jv", "jpo %Jv",
  203.   "jl %Jv", "jge %Jv", "jle %Jv", "jg %Jv",
  204. /* 9 */
  205.   "seto %Eb", "setno %Eb", "setc %Eb", "setnc %Eb",
  206.   "setz %Eb", "setnz %Eb", "setbe %Eb", "setnbe %Eb",
  207.   "sets %Eb", "setns %Eb", "setpe %Eb", "setpo %Eb",
  208.   "setl %Eb", "setge %Eb", "setle %Eb", "setg %Eb",
  209. /* a */
  210.   "push fs", "pop fs", 0, "bt %Ev,%Gv",
  211.   "shld %Ev,%Gv,%Ibb", "shld %Ev,%Gv,cl", 0, 0,
  212.   "push gs", "pop gs", 0, "bts %Ev,%Gv",
  213.   "shrd %Ev,%Gv,%Ibb", "shrd %Ev,%Gv,cl", 0, "imul %Gv,%Ev",
  214. /* b */
  215.   0, 0, "lss %Mp", "btr %Ev,%Gv",
  216.   "lfs %Mp", "lgs %Mp", "movzx %Gv,%Eb", "movzx %Gv,%Ew",
  217.   0, 0, "%g8 %Ev,%Ibb", "btc %Ev,%Gv",
  218.   "bsf %Gv,%Ev", "bsr %Gv,%Ev", "movsx %Gv,%Eb", "movsx %Gv,%Ew",
  219. /* c */
  220.   0, 0, 0, 0, 0, 0, 0, 0,
  221.   0, 0, 0, 0, 0, 0, 0, 0,
  222.   0, 0, 0, 0, 0, 0, 0, 0,
  223.   0, 0, 0, 0, 0, 0, 0, 0,
  224.   0, 0, 0, 0, 0, 0, 0, 0,
  225.   0, 0, 0, 0, 0, 0, 0, 0,
  226.   0, 0, 0, 0, 0, 0, 0, 0,
  227.   0, 0, 0, 0, 0, 0, 0, 0,
  228.   };
  229.  
  230. char *groups[][8] = {     /* group 0 is group 3 for %Ev set */
  231.   { "test %Ev,%Ivv", "test %Ev,%Ivv,", "not %Ev", "neg %Ev",
  232.     "mul %eax,%Ev", "imul %eax,%Ev", "div %eax,%Ev", "idiv %eax,%Ev" },
  233.   { "add%+-", "or", "adc%+-", "sbb%+-", "and", "sub%+-", "xor", "cmp%+-" },
  234.   { "rol", "ror", "rcl", "rcr", "shl", "shr", "shl", "sar" },
  235.   { "test %Eb,%Ibb", "test %Eb,%Ibb,", "not %Eb", "neg %Eb",
  236.     "mul al,%Eb", "imul al,%Eb", "div al,%Eb", "idiv al,%Eb" },
  237.   { "inc %Eb", "dec %Eb", 0, 0, 0, 0, 0, 0 },
  238.   { "inc %Ev", "dec %Ev", "call %Ev", "call %Ep",
  239.     "jmp %Ev", "jmp %Ep", "push %Ev", 0 },
  240.   { "sldt %Ew", "str %Ew", "lldt %Ew", "ltr %Ew",
  241.     "verr %Ew", "verw %Ew", 0, 0 },
  242.   { "sgdt %Ms", "sidt %Ms", "lgdt %Ms", "lidt %Ms",
  243.     "smsw %Ew", 0, "lmsw %Ew", 0 },
  244.   { 0, 0, 0, 0, "bt", "bts", "btr", "btc" }
  245.   };
  246.  
  247. /* zero here means invalid.  If first entry starts with '*', use st(i) */
  248. /* no assumed %EFs here.  Indexed by rm(modrm()) */
  249. char *f0[] = {0, 0, 0, 0, 0, 0, 0, 0};
  250. char *fop_9[]  = { "*fxch st,%GF" };
  251. char *fop_10[] = { "fnop", 0, 0, 0, 0, 0, 0, 0 };
  252. char *fop_12[] = { "fchs", "fabs", 0, 0, "ftst", "fxam", 0, 0 };
  253. char *fop_13[] = { "fld1", "fldl2t", "fldl2e", "fldpi",
  254.                    "fldlg2", "fldln2", "fldz", 0 };
  255. char *fop_14[] = { "f2xm1", "fyl2x", "fptan", "fpatan",
  256.                    "fxtract", "fprem1", "fdecstp", "fincstp" };
  257. char *fop_15[] = { "fprem", "fyl2xp1", "fsqrt", "fsincos",
  258.            "frndint", "fscale", "fsin", "fcos" };
  259. char *fop_21[] = { 0, "fucompp", 0, 0, 0, 0, 0, 0 };
  260. char *fop_28[] = { 0, 0, "fclex", "finit", 0, 0, 0, 0 };
  261. char *fop_32[] = { "*fadd %GF,st" };
  262. char *fop_33[] = { "*fmul %GF,st" };
  263. char *fop_36[] = { "*fsubr %GF,st" };
  264. char *fop_37[] = { "*fsub %GF,st" };
  265. char *fop_38[] = { "*fdivr %GF,st" };
  266. char *fop_39[] = { "*fdiv %GF,st" };
  267. char *fop_40[] = { "*ffree %GF" };
  268. char *fop_42[] = { "*fst %GF" };
  269. char *fop_43[] = { "*fstp %GF" };
  270. char *fop_44[] = { "*fucom %GF" };
  271. char *fop_45[] = { "*fucomp %GF" };
  272. char *fop_48[] = { "*faddp %GF,st" };
  273. char *fop_49[] = { "*fmulp %GF,st" };
  274. char *fop_51[] = { 0, "fcompp", 0, 0, 0, 0, 0, 0 };
  275. char *fop_52[] = { "*fsubrp %GF,st" };
  276. char *fop_53[] = { "*fsubp %GF,st" };
  277. char *fop_54[] = { "*fdivrp %GF,st" };
  278. char *fop_55[] = { "*fdivp %GF,st" };
  279. char *fop_60[] = { "fstsw ax", 0, 0, 0, 0, 0, 0, 0 };
  280.  
  281. char **fspecial[] = { /* 0=use st(i), 1=undefined 0 in fop_* means undefined */
  282.   0, 0, 0, 0, 0, 0, 0, 0,
  283.   0, fop_9, fop_10, 0, fop_12, fop_13, fop_14, fop_15,
  284.   f0, f0, f0, f0, f0, fop_21, f0, f0,
  285.   f0, f0, f0, f0, fop_28, f0, f0, f0,
  286.   fop_32, fop_33, f0, f0, fop_36, fop_37, fop_38, fop_39,
  287.   fop_40, f0, fop_42, fop_43, fop_44, fop_45, f0, f0,
  288.   fop_48, fop_49, f0, fop_51, fop_52, fop_53, fop_54, fop_55,
  289.   f0, f0, f0, f0, fop_60, f0, f0, f0,
  290.   };
  291.  
  292. char *floatops[] = { /* assumed " %EF" at end of each.  mod != 3 only */
  293. /*00*/ "fadd", "fmul", "fcom", "fcomp",
  294.        "fsub", "fsubr", "fdiv", "fdivr",
  295. /*08*/ "fld", 0, "fst", "fstp",
  296.        "fldenv", "fldcw", "fstenv", "fstcw",
  297. /*16*/ "fiadd", "fimul", "ficomw", "ficompw",
  298.        "fisub", "fisubr", "fidiv", "fidivr",
  299. /*24*/ "fild", 0, "fist", "fistp",
  300.        "frstor", "fldt", 0, "fstpt",
  301. /*32*/ "faddq", "fmulq", "fcomq", "fcompq",
  302.        "fsubq", "fsubrq", "fdivq", "fdivrq",
  303. /*40*/ "fldq", 0, "fstq", "fstpq",
  304.        0, 0, "fsave", "fstsww",
  305. /*48*/ "fiaddw", "fimulw", "ficomw", "ficompw",
  306.        "fisubw", "fisubrw", "fidivw", "fidivr",
  307. /*56*/ "fildw", 0, "fistw", "fistpw",
  308.        "fbldt", "fildq", "fbstpt", "fistpq"
  309.   };
  310.  
  311. static word8 getbyte(void)
  312. {
  313.   int s;
  314.   if (bufp >= bufe)
  315.   {
  316.     s = 20;
  317.     if ((vaddr & 0xfff) + s > 0x1000)
  318.       s = 0x1000 - (vaddr & 0xfff);
  319.     read_child(vaddr, buf, s);
  320.     bufe = s;
  321.     bufp = 0;
  322.   }
  323.   vaddr++;
  324. #ifndef FULLSCR
  325.   printf("%02x", buf[bufp]);
  326.   col+=2;
  327. #endif
  328.   return buf[bufp++];
  329. }
  330.  
  331. static int default_pick_sign;
  332.  
  333. static prefix;
  334. static modrmv;
  335. static sibv;
  336. static opsize;
  337. static addrsize;
  338.  
  339. static int modrm(void)
  340. {
  341.   if (modrmv == -1)
  342.     modrmv = getbyte();
  343.   return modrmv;
  344. }
  345.  
  346. static int
  347. sib(void)
  348. {
  349.   if (sibv == -1)
  350.     sibv = getbyte();
  351.   return sibv;
  352. }
  353.  
  354. #define mod(a)  (((a)>>6)&7)
  355. #define reg(a)  (((a)>>3)&7)
  356. #define rm(a)   ((a)&7)
  357. #define ss(a)   (((a)>>6)&7)
  358. #define indx(a) (((a)>>3)&7)
  359. #define base(a) ((a)&7)
  360.  
  361. /*------------------------------------------------------------------------*/
  362. static void
  363. uprintf (char *s, ...)
  364. { char **a = &s;
  365.   vsprintf(ubufp, s, a+1);
  366.   while (*ubufp) ubufp++;
  367. }
  368. /*------------------------------------------------------------------------*/
  369. static void
  370. uputchar (char c)
  371. {  if (c == '\t')
  372.   { do
  373.     { *ubufp++ = ' ';
  374.     } while ((ubufp-ubuf) % 8);
  375.   } else
  376.     *ubufp++ = c;
  377.   *ubufp = 0;
  378. }
  379. /*------------------------------------------------------------------------*/
  380. static int
  381. bytes (char c)
  382. { switch (c)
  383.   { case 'b':
  384.       return 1;
  385.     case 'w':
  386.       return 2;
  387.     case 'd':
  388.       return 4;
  389.     case 'v':
  390.       if (opsize == 32)
  391.         return 4;
  392.       else
  393.         return 2;
  394.   }
  395.   return 0;
  396. }
  397. /*------------------------------------------------------------------------*/
  398. static void
  399. ohex (char c, int extend, int optional, int defsize, int sign)
  400. {
  401. /*  static char *formats[4] = { "%#x", "%d", "%+d", "%+d" }; */
  402.   static char *formats[4] = { "%#x", "%#x", "%+#x", "%#x" }; 
  403.   char *fmt;
  404.   int n=0, s=0, i;
  405.   int32 delta;
  406.   unsigned char buf[6];
  407.   char *name;
  408.   fmt = formats[sign];
  409.  
  410.   switch (c)
  411.   { case 'a':
  412.       break;
  413.     case 'b':
  414.       n = 1;
  415.       break;
  416.     case 'w':
  417.       n = 2;
  418.       break;
  419.     case 'd':
  420.       n = 4;
  421.       break;
  422.     case 's':
  423.       n = 6;
  424.       break;
  425.     case 'c':
  426.     case 'v':
  427.       if (defsize == 32)
  428.         n = 4;
  429.       else
  430.         n = 2;
  431.       break;
  432.     case 'p':
  433.       if (defsize == 32)
  434.         n = 6;
  435.       else
  436.         n = 4;
  437.       s = 1;
  438.       break;
  439.     case 'x':
  440.       return;
  441.   }
  442.   for (i=0; i<n; i++)
  443.     buf[i] = getbyte();
  444.   for (; i<extend; i++)
  445.     buf[i] = (buf[i-1] & 0x80) ? 0xff : 0;
  446.   if (s)
  447.   {
  448.     uprintf("0x%02x%02x:", buf[n-1], buf[n-2]);
  449.     n -= 2;
  450.   }
  451.   switch (n)
  452.   {
  453.     case 1:
  454.       delta = *(signed char *)buf;
  455.       break;
  456.    case 2:
  457.       delta = *(signed short *)buf;
  458.       break;
  459.     case 4:
  460.       delta = *(signed long *)buf;
  461.       break;
  462.   }
  463.   if (sign == 3)
  464.     if (delta < 0)
  465.     { delta = 0 - delta;
  466.       uputchar ('-');
  467.     } else
  468.       uputchar ('+');
  469.   if (extend > n)
  470.   {
  471.     if (delta || !optional)
  472.     {
  473.       uprintf(fmt, delta);
  474.     }
  475.     return;
  476.   }
  477.   if ((n == 4) && sign < 2)
  478.   {
  479. #ifdef FULLSCR
  480.     if (delta >= 0 && delta < 0x1000) /* No labels there, only constants.  */
  481.       name = 0;
  482.     else
  483. #endif
  484.     name = syms_val2name(delta, &delta);
  485.     if (name)
  486.     {
  487.       uprintf("%s", name);
  488.       if (delta)
  489.         uprintf("+0x%lx", delta);
  490. /*        uprintf("+%lu", delta);  */
  491.       return;
  492.     }
  493.   }
  494.   switch (n)
  495.   {
  496.     case 1:
  497.       uprintf(fmt, (unsigned char)delta);
  498.       break;
  499.     case 2:
  500.       uprintf(fmt, (unsigned short)delta);
  501.       break;
  502.     case 4:
  503.       uprintf(fmt, (unsigned long)delta);
  504.       break;  
  505.   }
  506. }
  507. /*------------------------------------------------------------------------*/
  508. static char *reg_names[3][8]={
  509.   {"al" ,"cl" ,"dl" ,"bl" ,"ah" ,"ch" ,"dh" ,"bh" },
  510.   {"ax" ,"cx" ,"dx" ,"bx" ,"sp" ,"bp" ,"si" ,"di" },
  511.   {"eax","ecx","edx","ebx","esp","ebp","esi","edi"}
  512. };
  513.  
  514. static void
  515. reg_name (int which, char size)
  516. {
  517.   if (size == 'F')
  518.   {
  519.     uprintf("st(%d)", which);
  520.     return;
  521.   }
  522.   if (((size == 'v') && (opsize == 32)) || (size == 'd'))
  523.   {
  524.     uputchar('e');
  525.   }
  526.   if (size == 'b')
  527.   {
  528.     uputchar("acdbacdb"[which]);
  529.     uputchar("llllhhhh"[which]);
  530.   }
  531.   else
  532.   {
  533.     uputchar("acdbsbsd"[which]);
  534.     uputchar("xxxxppii"[which]);
  535.   }
  536. }
  537. /*------------------------------------------------------------------------*/
  538. static int
  539. do_sib (int m)
  540. {
  541.   static char *i_str[] = {
  542.     "+eax", "+ecx", "+edx", "+ebx", "", "+ebp", "+esi", "+edi" };
  543.   int pick_signed = default_pick_sign;
  544.   int s, i, b, extra=0;
  545.   s = ss(sib());
  546.   i = indx(sib());
  547.   b = base(sib());
  548.   if (b == 5)
  549.   {
  550.       if (m == 0)
  551.       {
  552.         ua_str("%p:[");
  553.         ohex('d', 4, 0, addrsize, 1);
  554.       }
  555.       else
  556.       {
  557.         ua_str("%p:[ebp");
  558.         pick_signed |= 2;
  559.       }
  560.   }
  561.   else
  562.   {
  563.     static char *sib_str[] = {
  564.       "%p:[eax", "%p:[ecx", "%p:[edx", "%p:[ebx", "%p:[esp", 0, "%p:[esi", "%p:[edi" };
  565.     pick_signed |= 2;
  566.     ua_str(sib_str[b]);
  567.     if ((b == i) && (b != 4) && (i != 5))
  568.       extra = 1;
  569.   }
  570.   if (extra == 0)
  571.   {
  572.     pick_signed |= 2;
  573.     uprintf(i_str[i]);
  574.   }
  575.   if (i != 4 && s)
  576.     uprintf("*%d", (1<<s)+extra);
  577.   return pick_signed;
  578. }
  579. /*------------------------------------------------------------------------*/
  580. static int modrm_extend;
  581.  
  582. static void
  583. do_modrm (char t)
  584. { int m = mod(modrm());
  585.   int r = rm(modrm());
  586.   int extend = (addrsize == 32) ? 4 : 2;
  587.   int pick_signed = default_pick_sign;
  588.   if (m == 3)
  589.   {
  590.     reg_name(r, t);
  591.     return;
  592.   }
  593.   if ((m == 0) && (r == 5) && (addrsize == 32))
  594.   {
  595.     ua_str("%p:[");
  596.     ohex('d', extend, 0, addrsize, 0);
  597.     uputchar(']');
  598.     return;
  599.   }
  600.   if ((m == 0) && (r == 6) && (addrsize == 16))
  601.   {
  602.     ua_str("%p:[");
  603.     ohex('w', extend, 0, addrsize, 0);
  604.     uputchar(']');
  605.     return;
  606.   }
  607.   if ((addrsize != 32) || (r != 4))
  608.     ua_str("%p:[");
  609.   if (addrsize == 16)
  610.   {
  611.     static char *r_str[] = {
  612.       "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" };
  613.     uprintf(r_str[r]);
  614.     pick_signed |= 2;
  615.   }
  616.   else
  617.   {
  618.     if (r == 4)
  619.       pick_signed |= do_sib(m);
  620.     else
  621.     {
  622.       uprintf(reg_names[2][r]);
  623.       pick_signed |= 2;
  624.     }
  625.   }
  626.   modrm_extend = extend;
  627.   ohex("xbv"[m], extend, 1, addrsize, pick_signed);
  628.   uputchar(']');
  629. }
  630. /*------------------------------------------------------------------------*/
  631. static void
  632. floating_point (int e1)
  633. { int esc = e1*8 + reg(modrm());
  634.   if (mod(modrm()) == 3)
  635.   {
  636.     if (fspecial[esc])
  637.     {
  638.       if (fspecial[esc][0] && (fspecial[esc][0][0] == '*'))
  639.       {
  640.         ua_str(fspecial[esc][0]+1);
  641.       }
  642.       else
  643.       {
  644.     ua_str(fspecial[esc][rm(modrm())]);
  645.       }
  646.     }
  647.     else
  648.     {
  649.       ua_str(floatops[esc]);
  650.       ua_str(" %EF");
  651.     }
  652.   }
  653.   else
  654.   {
  655.     ua_str(floatops[esc]);
  656.     ua_str(" %EF");
  657.   }
  658. }
  659.  
  660. /*------------------------------------------------------------------------*/
  661. static void
  662. percent (char c, char **tptr)
  663. {
  664.   word32 vofs = 0, delta;
  665.   char *name;
  666.   int default_signed = default_pick_sign;
  667.   char t = *(*tptr)++, it;
  668.   int extend = (addrsize == 32) ? 4 : 2;
  669.   int iextend;
  670.  
  671.   if (c != '+')
  672.   {
  673.     if (t == '-')
  674.     {
  675.       default_signed = 1;
  676.       t = *(*tptr)++;
  677.     }
  678.     else if (t == '+')
  679.     {
  680.       default_signed = 2;
  681.       t = *(*tptr)++;
  682.     }
  683.   }
  684.   switch (c)
  685.   {
  686.     case 'A':
  687.       ohex(t, extend, 0, addrsize, 0);
  688.       break;
  689.     case 'C':
  690.       uprintf("cr%d", reg(modrm()));
  691.       break;
  692.     case 'D':
  693.       uprintf("dr%d", reg(modrm()));
  694.       break;
  695.     case 'E':
  696.       do_modrm(t);
  697.       break;
  698.     case 'G':
  699.       if (t == 'F')
  700.         reg_name(rm(modrm()), t);
  701.       else
  702.         reg_name(reg(modrm()), t);
  703.       break;
  704.     case 'I':
  705.       it = *(*tptr)++;
  706.       switch (t)
  707.       {
  708.         case 'b':
  709.           iextend = 1;
  710.           break;
  711.         case 'v':
  712.           iextend = extend;
  713.           break;
  714.     default:
  715.           iextend = 0;
  716.           break;
  717.       }
  718.       ohex(it, iextend, 0, opsize, default_signed);
  719.       break;
  720.     case 'J':
  721.       switch (bytes(t))
  722.       {
  723.         case 1:
  724.           vofs = (int8)getbyte();
  725.           break;
  726.         case 2:
  727.           vofs = getbyte();
  728.           vofs += getbyte()<<8;
  729.           vofs = (int16)vofs;
  730.           break;
  731.         case 4:
  732.           vofs = (word32)getbyte();
  733.           vofs |= (word32)getbyte() << 8;
  734.           vofs |= (word32)getbyte() << 16;
  735.           vofs |= (word32)getbyte() << 24;
  736.           break;
  737.       }
  738.       name = syms_val2name(vofs+vaddr, &delta);
  739.       uprintf("%s", name);
  740.       if (delta)
  741. /*        uprintf("+%lu (0x%lx %c)", delta, vofs+vaddr,
  742.                 (vofs & 0x80000000L) ? 0x1e : 0x1f);    */
  743.         uprintf("+0x%lx (0x%lx %c)", delta, vofs+vaddr,
  744.                 (vofs & 0x80000000L) ? 0x1e : 0x1f);
  745.       break;                       /*   ^^ +   ^^ : Should be up/down arrows.*/
  746.     case 'M':
  747.       do_modrm(t);
  748.       break;
  749.     case 'O':
  750.       ua_str("%p:[");
  751.       ohex(t, extend, 0, addrsize, 0);
  752.       uputchar(']');
  753.       break;
  754.     case 'R':
  755.       do_modrm(t);
  756.       break;
  757.     case 'S':
  758.       uputchar("ecsdfg"[reg(modrm())]);
  759.       uputchar('s');
  760.       break;
  761.     case 'T':
  762.       uprintf("tr%d", reg(modrm()));
  763.       break;
  764.     case 'X':
  765.       uprintf("ds:[");
  766.       if (addrsize == 32)
  767.         uputchar('e');
  768.       uprintf("si]");
  769.       break;
  770.     case 'Y':
  771.       uprintf("es:[");
  772.       if (addrsize == 32)
  773.         uputchar('e');
  774.       uprintf("di]");
  775.       break;
  776.     case '2':
  777.       ua_str(second[getbyte()]);
  778.       break;
  779.     case 'e':
  780.       if (opsize == 32)
  781.       {
  782.         if (t == 'w')
  783.           uputchar('d');
  784.     else
  785.         {
  786.           uputchar('e');
  787.           uputchar(t);
  788.         }
  789.       }
  790.       else
  791.         uputchar(t);
  792.       break;
  793.     case 'f':
  794.       floating_point(t-'0');
  795.       break;
  796.     case 'g':
  797.       ua_str(groups[t-'0'][reg(modrm())]);
  798.       break;
  799.     case 'p':
  800.       switch (t)
  801.       {
  802.         case 'c':
  803.         case 'd':
  804.         case 'e':
  805.         case 'f':
  806.         case 'g':
  807.         case 's':
  808.           prefix = t;
  809.           ua_str(opmap1[getbyte()]);
  810.       break;
  811.         case ':':
  812.           if (prefix)
  813.             uprintf("%cs:", prefix);
  814.           break;
  815.         case ' ':
  816.           ua_str(opmap1[getbyte()]);
  817.           break;
  818.       }
  819.       break;
  820.     case 's':
  821.       switch (t)
  822.       {
  823.         case 'a':
  824.           addrsize = 48 - addrsize;
  825.           ua_str(opmap1[getbyte()]);
  826.           break;
  827.         case 'o':
  828.           opsize = 48 - opsize;
  829.           ua_str(opmap1[getbyte()]);
  830.           break;
  831.       }
  832.       break;
  833.     case '+':
  834.       switch (t)
  835.       {
  836.         case '-':
  837.           default_pick_sign = 1;
  838.           break;
  839.         case '+':
  840.           default_pick_sign = 2;
  841.           break;
  842.         default:
  843.           default_pick_sign = 0;
  844.           break;
  845.       }
  846.   }
  847. }
  848. /*------------------------------------------------------------------------*/
  849. static void
  850. ua_str (char *s)
  851. { int c;
  852.   if (s == 0)
  853.   {
  854.     uprintf("<invalid>");
  855.     return;
  856.   }
  857.   while ((c = *s++) != 0)
  858.   {
  859.     if (c == '%')
  860.     {
  861.       c = *s++;
  862.       percent(c, &s);
  863.     }
  864.     else
  865.       if (c == ' ')
  866.         uputchar('\t');
  867.       else
  868.         uputchar(c);
  869.   }
  870. }
  871.  
  872. #ifdef SOURCE_LIST
  873. /*
  874. ** A little brute force hacking and hey presto! A source debugger!
  875. ** Courtesy of Kent Williams williams@herky.cs.uiowa.edu
  876. **
  877. ** KNOWN BUGS:
  878. ** The program will summarily terminate if you run out
  879. ** of memory while you're looking for all the line offsets.  Since
  880. ** a two thousand line source file only creats an 8K array, and the
  881. ** symbol table goes into virtual memory, this shouldn't happen too
  882. ** often.
  883. **
  884. ** One file is left open for reading indefinitely.
  885. */
  886. #include <stdlib.h>
  887. #include <string.h>
  888. /*
  889. ** keep the source line offsets in virtual memory, so you can
  890. ** debug big programs
  891. */
  892. extern word32 salloc(word32 size);
  893. #define symsput(where,ptr,size)     memput(where,ptr,size)
  894. #define symsget(where,ptr,size)     memget(where,ptr,size)
  895.  
  896. /*
  897. ** for each file encountered, keep an array of line start offsets
  898. ** so you can seek into the file to display the current line.
  899. */
  900. typedef struct {
  901.         char *filename;
  902.         long *offsets;
  903. } line_info;
  904.  
  905. static line_info *files;
  906. static last_file = 0;
  907.  
  908. /*
  909. ** add_file -- add a file to the source line database
  910. */
  911. static int
  912. add_file(char *name) {
  913.         FILE *f = fopen(name,"rb");
  914.         char c;
  915.         long *lines,curpos;
  916.         unsigned curline = 0;
  917.  
  918.         if(!f)
  919.                 return -1;
  920.  
  921.         if (files == 0)
  922.           files = (line_info *)malloc(sizeof(line_info));
  923.         else
  924.       files = realloc(files, (last_file+1) * sizeof(line_info));
  925.  
  926.     files[last_file].filename = strdup(name);
  927.  
  928.         /*
  929.         ** build an array of line offsets in real memory.
  930.         */
  931.         lines = malloc(sizeof(long));
  932.         lines[curline++] = curpos = 0L;
  933.  
  934.         while((c = getc(f)) != EOF) {
  935.                 curpos++;
  936.                 if(c == '\n') {
  937.                         lines = realloc(lines,sizeof(long)*(curline+1));
  938.                         lines[curline++] = curpos;
  939.                 }
  940.         }
  941.         /*
  942.         ** now move the whole array into virtual memory
  943.         */
  944.         files[last_file].offsets = lines;
  945.         fclose(f);
  946.  
  947.         last_file++;
  948.         return 0;
  949. }
  950.  
  951. static line_info *
  952. find_file(char *name) {
  953.         int i;
  954.         for(i = 0; i < last_file; i++)
  955.                 if(strcmp(name,files[i].filename) == 0)
  956.                         return &files[i];
  957.         if(add_file(name) == -1)
  958.                         return NULL;
  959.     return find_file(name);
  960. }
  961.  
  962. /*
  963. ** myfopen -- cache the most recently accessed source file
  964. ** so you aren't constantly reopening a new file
  965. */
  966. static FILE *
  967. myfopen(char *name) {
  968.         static char fname[80] = "";
  969.         static FILE *current = NULL;
  970.         if(current != NULL && strcmp(fname,name) == 0)
  971.                         return current;
  972.         if(current != NULL) fclose(current);
  973.         strcpy(fname,name);
  974.         return (current = fopen(name,"rb"));
  975. }
  976. /*------------------------------------------------------------------------*/
  977. /*
  978. ** put_source_line -- print the current source line, along with
  979. ** the line # and file name, if necessary.
  980. */
  981. #ifdef FULLSCR
  982. static void
  983. put_source_line(int fmt, char *name, int line, char *result)
  984. #else
  985. static void
  986. put_source_line(int fmt,char *name,int line)
  987. #endif
  988. {
  989.         line_info *current = find_file(name);
  990.         FILE *cur;
  991. #ifdef FULLSCR
  992.     /* See below */
  993.     char *sbuf, *chp;
  994. #endif
  995.         if(current == NULL) {
  996.     regular:
  997. #ifdef FULLSCR
  998.       sbuf = alloca (100);
  999.           if (fmt == 0)
  1000.         sprintf (sbuf, " (%s#%d):", name, line);
  1001.           else
  1002.         sprintf (sbuf, "#%d:", line);
  1003.       strcat (result, sbuf);
  1004. #else
  1005.           if(fmt == 0)
  1006.                   printf(" (%s#%d):\n", name, line);
  1007.           else
  1008.                   printf("#%d:\n", line);
  1009. #endif
  1010.         } else {
  1011. #ifdef FULLSCR
  1012.             /* I really hate set a maximum like this, but setting it
  1013.            this high will hopefully not feel like a maximum.  */
  1014.                 char buf[1000];
  1015. #else
  1016.                 char buf[70];
  1017. #endif
  1018.                 long offset;
  1019.                 if((cur = myfopen(name)) == NULL)
  1020.                         goto regular;
  1021.                 /*
  1022.                 ** get the symbol out of virtual memory
  1023.                 */
  1024.                 offset = current->offsets[line-1];
  1025.                 fseek(cur,offset,0);
  1026.                 /*
  1027.                 ** truncate line so it fits on screen.
  1028.                 */
  1029.         fgets(buf,sizeof(buf)-2,cur);
  1030. #ifdef FULLSCR
  1031.         if ((chp = strchr (buf, '\n')))
  1032.           if (chp != buf && chp[-1] == '\r')
  1033.             chp [-1] = '\0';
  1034.           else
  1035.             *chp = '\0';
  1036.         sbuf = alloca (sizeof (buf) + 100);
  1037.         if (fmt == 0)
  1038.           sprintf (sbuf, " (%s#%d): %s", name, line, buf);
  1039.         else
  1040.           sprintf (sbuf, "#%d: %s", line, buf);
  1041.         strcat (result, sbuf);
  1042. #else
  1043.                 if(strchr(buf,'\n') == NULL)
  1044.                         strcat(buf,"\n");
  1045.                 if(fmt == 0)
  1046.                         printf(" (%s#%d): %s", name, line,buf);
  1047.                 else
  1048.                         printf("#%d: %s",line,buf);
  1049. #endif
  1050.         }
  1051. }
  1052.  
  1053. #endif
  1054.  
  1055. int last_unassemble_unconditional;
  1056. int last_unassemble_jump;
  1057. int last_unassemble_extra_lines;
  1058. /* Please read the above regarding this max.  */
  1059. char last_unassemble_text[1100];
  1060.  
  1061. char *
  1062. unassemble_proper (word32 v, int *len)
  1063. {
  1064.   prefix = 0;
  1065.   modrmv = sibv = -1;
  1066.   opsize = addrsize = seg_size;
  1067.   vaddr = v;
  1068.   bufp = bufe = 0;
  1069.   col = 0;
  1070.   ubufp = ubuf;
  1071.   ua_str(opmap1[getbyte()]);
  1072.   
  1073.   *len = vaddr - v;
  1074.   return ubuf;
  1075. }
  1076.  
  1077. char *
  1078. unassemble_source (word32 v)
  1079. {
  1080.   word32 delta;
  1081.   char *name, *lname, *result = last_unassemble_text;
  1082.   int linenum;
  1083.  
  1084.   result[0] = '\0';
  1085.  
  1086.   name = syms_val2name (v, &delta);
  1087.   if (!delta && (name[0] != '0'))
  1088.     {
  1089.       strcat (strcat (result, name), "()");
  1090.       lname = syms_val2line (v, &linenum, 1);
  1091.       if (lname)
  1092.     put_source_line (0, lname, linenum, result);
  1093.       else
  1094.     strcat (result, ":");
  1095.     }
  1096.   else
  1097.     {
  1098.       lname = syms_val2line (v, &linenum, 1);
  1099.       if (lname)
  1100.     put_source_line (1, lname, linenum, result);
  1101.       else
  1102.     return NULL;
  1103.     }
  1104.   return result;
  1105. }
  1106.  
  1107. #ifndef FULLSCR
  1108. word32 unassemble(word32 v, int showregs)
  1109. {
  1110.   int a,b,n,wi, linenum;
  1111.   char *cmp, *brp;
  1112.   word8 *wp;
  1113.   word32 delta;
  1114.   char *name, *lname;
  1115.   char *regpos;
  1116.  
  1117.   default_pick_sign = 0;
  1118.   ansi(A_yellow);
  1119.   last_unassemble_unconditional = 0;
  1120.   last_unassemble_jump = 0;
  1121.   last_unassemble_extra_lines = 0;
  1122.   name = syms_val2name(v, &delta);
  1123.   if (!delta && (name[0] != '0'))
  1124.   {
  1125.     printf("%s()", name);
  1126.     lname = syms_val2line(v, &linenum, 1);
  1127.     if (lname)
  1128. #ifndef SOURCE_LIST
  1129.       printf(" (%s#%d):\n", lname, linenum);
  1130. #else
  1131.       put_source_line(0,lname,linenum);
  1132. #endif
  1133.     else
  1134.       printf(":\n");
  1135.     last_unassemble_extra_lines++;
  1136.   }
  1137.   else
  1138.   {
  1139.     lname = syms_val2line(v, &linenum, 1);
  1140.     if (lname)
  1141.     {
  1142. #ifndef SOURCE_LIST
  1143.       printf("#%d:\n", linenum);
  1144. #else
  1145.       put_source_line(1,lname,linenum);
  1146. #endif
  1147.       last_unassemble_extra_lines++;
  1148.     }
  1149.   }
  1150.  
  1151.   ansi(A_grey);
  1152.   printf("%08lx: ", v);
  1153. #if 0
  1154.   if (!page_is_valid(v+ARENA) || !page_is_valid(v+5+ARENA))
  1155.   {
  1156.     printf("<bad address>\n");
  1157.     return v;
  1158.   }
  1159. #endif
  1160.  
  1161.   prefix = 0;
  1162.   modrmv = sibv = -1;
  1163.   opsize = addrsize = seg_size;
  1164.   vaddr = v;
  1165.   bufp = bufe = 0;
  1166.   col = 0;
  1167.   ubufp = ubuf;
  1168.   ua_str(opmap1[getbyte()]);
  1169.   do {
  1170.     putchar(' ');
  1171.     col++;
  1172.   } while (col < 15);
  1173.   col += strlen(ubuf);
  1174.   do {
  1175.     uputchar(' ');
  1176.     col++;
  1177.   } while (col < 43);
  1178.  
  1179.   ansi(A_cyan);
  1180.   printf("%s", ubuf);
  1181.   ansi(A_grey);
  1182.  
  1183.   if ((strncmp(ubuf, "jmp ", 4) == 0)
  1184.      || (strncmp(ubuf, "ret", 3) == 0))
  1185.     last_unassemble_unconditional = 1;
  1186.   if (ubuf[0] == 'j')
  1187.     last_unassemble_jump = 1;
  1188.  
  1189.   if (!showregs)
  1190.   {
  1191.     putchar('\n');
  1192.     return vaddr;
  1193.   }
  1194.  
  1195.   col -= 43; /* total 25 columns left */
  1196.   wp = (word8 *)&(a_tss.tss_eax);
  1197.   cmp = strchr(ubuf+8, ',');
  1198.   brp = strchr(ubuf+8, '[');
  1199.   if (!cmp) cmp = ubuf+8;
  1200.   if (!brp) brp = ubufp;
  1201.   if (brp < cmp) cmp = brp;
  1202.   if (strncmp(ubuf, "mov ", 4))
  1203.     cmp = ubuf+8;
  1204.   for (b=0; b<8; b++)
  1205.   {
  1206.     for (a=2; a>=0; a--)
  1207.     {
  1208.       n = (a==0) ? 1 : ((a==1) ? 2 : 4);
  1209.       if (regpos = strstr(cmp, reg_names[a][b]))
  1210.       {
  1211.     if (!isalnum (regpos[-1]) && (regpos[-1] != '_'))
  1212.     {
  1213.       col += strlen(reg_names[a][b])+n*2+2;
  1214.       if (col > 29)
  1215.       {
  1216.         printf("\n%53s", "");
  1217.         col = 0;
  1218.       }
  1219.       printf("%s=", reg_names[a][b]);
  1220.       if (a == 0)
  1221.         wi = (b&3)*4 + (b>>2);
  1222.       else
  1223.         wi = b*4;
  1224.       while (n)
  1225.       {
  1226.         n--;
  1227.         printf("%02x", wp[wi+n]);
  1228.       }
  1229.       putchar(' ');
  1230.       break;
  1231.     }
  1232.       }
  1233.     }
  1234.   }
  1235.   putchar('\n');
  1236.   return vaddr;
  1237. }
  1238. #endif /* FULLSCR */
  1239.